#include "complejo.h"
#include <iostream>
#include <sstream>

Complex::Complex(const float re, const float im){
		this->real = Float(re);
		this->imaginario =  Float(im);
}

Complex::Complex(const Float& re, const Float& im){
	this->real = re;
	this->imaginario = im;
}

Complex::Complex() {
    //
}


	/*****************************
	 *operadores
	 ****************************/
Complex operator+(const Complex& z, const Complex& w){
	Complex ret(z);
	ret.suma(w);
	return ret;
}

Complex operator-(const Complex& z, const Complex& w){
	return Complex( z.Re()-w.Re(), z.Im()-w.Im() );
}

Complex operator*(const Complex& z, const Complex& w){
	Complex ret(z);
	ret.producto(w);
	return ret;
}

Complex operator*(const Float& lambda, const Complex& z){
	Complex ret(z);
	ret.producto(lambda);
	return ret;
}


Complex& Complex::suma(const Complex& z){
	this->real += z.Re();
	this->imaginario += z.Im();
	return *this;
}

Complex& Complex::producto(const Complex& z){

	// por comodidad a this->imaginario lo llamo wi y a this->real lo llamo wr
	Float wr = this->real;
	this->real *= z.Re();
	this->real = this->real - (this->imaginario * z.Im());
	this->imaginario *= z.Re();
	wr*= z.Im();
	this->imaginario += wr;


	return *this;
}

Complex& Complex::producto(const Float& lambda){
	this->real *= lambda;
	this->imaginario *= lambda;
	return *this;
}

void Complex::cuadrado(){
	Float i = this->real;
    i *= this->imaginario;
    i *= Float(2);
    Float temp = this->real;
    temp -= this->imaginario;
    temp *= (this->real + this->imaginario);
    this->real = temp;
    this->imaginario = i;
}
Float Complex::moduloModulo() const{
	Float ret(this->real);
	Float im(this->imaginario);
	ret*=ret;
	im *= im;
	ret+=im;
	return ret;
}

Float Complex::Re() const {
	return this->real;
}


Float Complex::Im() const {
	return this->imaginario;
}

/*********************
** comparaciones y asignaciones
*****************************/
bool Complex::operator==(const Complex& z) const{
	return (this->real == z.Re()) && (this->imaginario == z.Im());

}

bool Complex::operator!=(const Complex& z) const{
	return !(*this == z);
}



/*********************
** setter
**************************/
Complex& Complex::setRe(Float r){
	this->real = r;
	return *this;
}

Complex& Complex::setIm(Float i){ // referenciaaaaaaaaaa :'(
	this->imaginario = i;
	return *this;
}

string Complex::mostrar() const{
    stringstream ss;
    ss << "(" << this->Re() << "," << this->Im() << ")" ;
    return ss.str();
}

/*******************
** STREAM
**********************/
ostream & operator<<(ostream & out, const Complex& comp) {
    out << comp.mostrar();
    return out;
}

